package asr_server

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	nls "github.com/aliyun/alibabacloud-nls-go-sdk"
	"log"
	"os"
	"sync/atomic"
	"xiaozhi/config"
)

func (asr *Asr) Init() {
	asr.Type = "stt"
	asr.Result = make(chan string, 10)
}

func (asr *Asr) Start(data []byte, num int) {
	asr.Init()
}

type AsrUserParam struct {
	Logger *nls.NlsLogger
	Asr    *Asr
}

func onTaskFailed(text string, param interface{}) {
	a, ok := param.(*AsrUserParam)
	if !ok {
		log.Default().Fatal("invalid logger")
		return
	}

	a.Logger.Println("TaskFailed:", text)
}

func onStarted(text string, param interface{}) {
	a, ok := param.(*AsrUserParam)
	if !ok {
		log.Default().Fatal("invalid logger")
		return
	}

	a.Logger.Println("onStarted:", text)
}

func onSentenceBegin(text string, param interface{}) {
	_, ok := param.(*AsrUserParam)
	if !ok {
		log.Default().Fatal("invalid logger")
		return
	}

	//logger.Println("onSentenceBegin:", text)
}

func onSentenceEnd(text string, param interface{}) {
	a, ok := param.(*AsrUserParam)
	if !ok {
		log.Default().Fatal("invalid logger")
		return
	}

	//logger.Println("onSentenceEnd:", text)
	extractAndLogResult(text, a.Logger, a.Asr.Result)
}

func onResultChanged(text string, param interface{}) {
	a, ok := param.(*AsrUserParam)
	if !ok {
		log.Default().Fatal("invalid logger")
		return
	}

	//logger.Println("onResultChanged:", text)
	extractAndLogResult(text, a.Logger, a.Asr.Result)
}

func onCompleted(text string, param interface{}) {
	a, ok := param.(*AsrUserParam)
	if !ok {
		log.Default().Fatal("invalid logger")
		return
	}

	//logger.Println("onCompleted:", text)
	extractAndLogResult(text, a.Logger, a.Asr.Result)
}

func onClose(param interface{}) {
	a, ok := param.(*AsrUserParam)
	if !ok {
		log.Default().Fatal("invalid logger")
		return
	}

	a.Logger.Println("onClosed:")
}

func waitReady(ch chan bool, logger *nls.NlsLogger) error {
	select {
	case done := <-ch:
		if !done {
			logger.Println("Wait failed")
			return errors.New("wait failed")
		}
		logger.Println("Wait done")
		return nil
		//	//case <-time.After(1 * time.Second):
		//	//	logger.Println("Wait timeout")
		//	//	return errors.New("wait timeout")
	}
}

func extractAndLogResult(text string, logger *nls.NlsLogger, param interface{}) {
	var frameData map[string]interface{}
	err := json.Unmarshal([]byte(text), &frameData)
	if err != nil {
		logger.Printf("Failed to unmarshal frame: %v", err)
		return
	}

	payload, ok := frameData["payload"].(map[string]interface{})
	if !ok {
		logger.Println("Payload not found in frame")
		return
	}

	result, ok := payload["result"].(string)
	if !ok {
		logger.Println("Result not found in payload")
		return
	}
	// 处理提取的结果
	// 从param中获取Asr实例的通道
	asrChan, ok := param.(chan string)
	//fmt.Println("param:", param)
	if !ok {
		logger.Println("Invalid param type, expected chan string")
		return
	}

	// 将结果发送到通道
	asrChan <- result
	logger.Printf("Asr result: %s", result)
}

func (asr *Asr) OnALYAsr(buffers []byte) {
	param := nls.SpeechTranscriptionStartParam{
		Format:                         config.NewAsrConfig().Format,
		SampleRate:                     config.NewAsrConfig().SampleRate,
		EnablePunctuationPrediction:    config.NewAsrConfig().EnablePunctuationPrediction,
		EnableInverseTextNormalization: config.NewAsrConfig().EnableInverseTextNormalization,
		EnableIntermediateResult:       config.NewAsrConfig().EnableIntermediateResult,
		MaxSentenceSilence:             config.NewAsrConfig().MaxSentenceSilence,
		EnableWords:                    config.NewAsrConfig().EnableWords,
	}
	alyConfig, err := nls.NewConnectionConfigWithAKInfoDefault(config.NewAsrConfig().ApiUrl, config.NewAsrConfig().AppKey, config.NewAsrConfig().AccessKeyId, config.NewAsrConfig().AccessKeySecret)
	if err != nil {
		log.Fatal(err)
	}
	reader := bytes.NewReader(buffers)
	buff := nls.LoadPcmInChunk(reader, 960)
	logger := nls.NewNlsLogger(os.Stderr, "ASR ", log.LstdFlags|log.Lmicroseconds)
	asrUserParam := new(AsrUserParam)
	asrUserParam.Asr = asr
	asrUserParam.Logger = logger
	logger.SetDebug(true)

	st, err := nls.NewSpeechTranscription(alyConfig, logger,
		onTaskFailed, onStarted,
		onSentenceBegin, onSentenceEnd, onResultChanged,
		onCompleted, onClose, asrUserParam)
	if err != nil {
		logger.Println(err)
		return
	}
	//defer

	testEx := make(map[string]interface{})
	testEx["demo"] = "hello"
	//
	atomic.AddInt64(&reqNum, 1)
	//logger.Println("ST start")
	ready, err := st.Start(param, testEx)
	if err != nil {
		atomic.AddInt64(&fail, 1)
		logger.Println("Failed to start transcription:", err)
		return
	}

	err = waitReady(ready, logger)
	if err != nil {
		atomic.AddInt64(&fail, 1)
		logger.Println("Wait failed:", err)
		return
	}

	// 从 buffers 通道中读取数据块并发送
	//fmt.Println("start send audio data", buffers)
	for _, b := range buff.Data {
		if len(b.Data) == 0 {
			logger.Println("No data to send")
			continue
		}
		fmt.Println("send audio data", b.Data)
		err = st.SendAudioData(b.Data)
		if err != nil {
			logger.Println("Failed to send audio data:", err)
			//return
		}
		//time.After(time.Millisecond * 2)

		logger.Println("send audio done")
	}
	//for _, data := range buff.Data {
	//	if data != nil {
	//		err := st.SendAudioData(data.Data)
	//		if err != nil {
	//			logger.Println("Failed to send audio data:", err)
	//			return
	//		}
	//	}
	//}
	//err = st.SendAudioData(buffers)
	//if err != nil {
	//	logger.Println("Failed to send audio data:", err)
	//	//return
	//}
	//logger.Println("All audio data sent, stopping transcription")
	ready, err = st.Stop()
	if err != nil {
		//atomic.AddInt64(&fail, 0.5)
		logger.Println("Failed to stop transcription:", err)
		//return
	}

	err = waitReady(ready, logger)
	if err != nil {
		atomic.AddInt64(&fail, 1)
		logger.Println("Wait failed after stopping transcription:", err)
		//return
	}
	st.Shutdown()
	logger.Println("Sr done")
	close(asr.Result)
}
